package org.ytoh.configurations; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; import org.apache.commons.beanutils.PropertyUtils; /** * Sandbox listens for property changes and reloads other properties if any * side-effects changed their underlying {@link Field}s. * * @author ytoh */ public class Sandbox implements PropertyChangeListener { /** property references */ private List<AbstractProperty> properties; /** object declaring the properties */ private Object sandbox; /** * Factory method creating a sandboxed version of the supplied object. * * @param sandbox object to sandbox * @return a sandboxed object */ public static final Sandbox newInstance(Object sandbox) { return new Sandbox(sandbox); } /** * Create a <code>Sandbox</code> instance based on the supplied object. * * @param sandbox */ private Sandbox(Object sandbox) { this(); this.sandbox = sandbox; } /** * Create an empty <code>Sandbox</code> instance. */ private Sandbox() { this.properties = new ArrayList<AbstractProperty>(); } /** * Adds properties to this sandbox. * * @param property */ public void addProperty(AbstractProperty property) { property.addStorePropertyChangeListener(this); properties.add(property); } /** * Listen for property changes and detect side-effects. If any side-effects * are detected reload the relevant properties. * * @see PropertyChangeListener#propertyChange(java.beans.PropertyChangeEvent) */ public void propertyChange(PropertyChangeEvent evt) { try { for (AbstractProperty defaultProperty : properties) { if (evt.getSource() != defaultProperty) { defaultProperty.setValue(PropertyUtils.getProperty(sandbox, defaultProperty.getFieldName()), false); // if the property has a state associated try updating the property state String fieldName = defaultProperty.getFieldName(); // workaround: PropertyUtils does not property detect the state property for single letter properties if (fieldName.length() == 1) { fieldName = fieldName.toUpperCase(); } if (PropertyUtils.isReadable(sandbox, fieldName + "State")) { defaultProperty.setPropertyState((PropertyState) PropertyUtils.getProperty(sandbox, fieldName + "State")); } } } } catch (IllegalAccessException ex) { Logger.getLogger(Sandbox.class.getName()).log(Level.SEVERE, null, ex); } catch (InvocationTargetException ex) { Logger.getLogger(Sandbox.class.getName()).log(Level.SEVERE, null, ex); } catch (NoSuchMethodException ex) { Logger.getLogger(Sandbox.class.getName()).log(Level.SEVERE, null, ex); } } }